﻿using CaseManagerLibrary.Auth;
using CaseManagerLibrary.Http;
using CaseManagerLibrary.Log;
using CaseManagerLibrary.Models;
using Newtonsoft.Json;
using PSDClientService;
using PSDClientService.SystemSettings;
using PSDLib;
using PSDLib.Models;
using PSDLib.Protocols;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace PSDClientService.Burn
{
    public class BurnContext
    {
        public ILog Logger
        {
            get
            {
                return ClientContext.Logger;
            }
        }

        public bool RunAsService { get; set; }

        public bool Running { get; set; }

        public bool Burning { get; set; }

        public bool Closing { get; set; }

        public string UUID
        {
            get
            {
                return ClientContext.UUID;
            }
            set
            {
                ClientContext.UUID = value;
            }
        }

        public dl_download_device Device
        {
            get
            {
                return ClientContext.Device;
            }
            set
            {
                ClientContext.Device = value;
            }
        }
        public ClientServiceContext ClientContext { get; set; }
        public BurnManager BurnManager { get; set; }
        public BurnRuntime BurnRuntime { get; set; }

        public object lock_burn = new object();

        public BurnContext(ClientServiceContext clientContext)
        {
            Running = false;
            Closing = false;
            Burning = false;

            ClientContext = clientContext;

            //DeviceManager = new BurnDeviceManager(this);
            clientContext.DeviceManager.OnGetRecordingDevice += DeviceManager_OnGetRecordingDevice;
            clientContext.DeviceManager.OnDetectRecorder += DeviceManager_OnDetectRecorder;
            clientContext.DeviceManager.OnUpdateCapacity += DeviceManager_OnUpdateCapacity;
            clientContext.DeviceManager.OnBurnSuccess += DeviceManager_OnBurnSuccess;
            clientContext.DeviceManager.OnBurnError += DeviceManager_OnBurnError;
            clientContext.DeviceManager.OnBurnProgress += DeviceManager_OnBurnProgress;
            clientContext.DeviceManager.OnBurnCancel += DeviceManager_OnBurnCancel;

            BurnManager = new BurnManager(this);
            BurnManager.OnBurnJobDenied += BurnManager_OnBurnJobDenied;

            BurnRuntime = new BurnRuntime();
        }

        private void BurnManager_OnBurnJobDenied(BurnJob job, int dvdNum, int resultCode)
        {
            //BurnJobDeniedMessage msg = new BurnJobDeniedMessage();
            //msg.BurnJob = job;
            //msg.DVDNum = dvdNum;
            //msg.ResultCode = resultCode;

            //ClientContext.MessageManager.SendToServer(msg);

            var bj = BurnRuntime.BurnJobs.Where(t => t.Id == job.Id).FirstOrDefault();

            if (bj != null)
            {
                bj.State = resultCode;
            }
        }

        /// <summary>
        /// 初始化刻录
        /// </summary>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <param name="logtype"></param>
        /// <param name="runAsService"></param>
        /// <returns></returns>
        public HResult Init(bool runAsService)
        {
            RunAsService = runAsService;

            HResult result = new HResult() { success = true };

            //foreach (var recorder in ClientContext.DeviceManager.RecorderList)
            //{
            //    BurnManager.CreateBurnJobQueue(recorder);
            //}

            Closing = false;

            return result;
        }

        /// <summary>
        /// 启动刻录监听
        /// </summary>
        public void OpenBurnClient()
        {
            try
            {
                Running = true;
                BurnManager.Start();
                Logger.Info("PSDBurn已启动");
            }
            catch (Exception ex)
            { }
        }

        /// <summary>
        /// 停止刻录监听
        /// </summary>
        public void CloseBurnClient()
        {
            try
            {
                //MessageManager.Stop();
                Running = false;
                BurnManager.Stop();
                Logger.Info("PSDBurn已停止");
            }
            catch (Exception ex)
            { }
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        /// <param name="exit"></param>
        public void Dispose(bool exit = true)
        {
            Running = false;

            if (exit)
            {
                Logger.Close();
            }
        }

        /// <summary>
        /// 得到一个光驱设备后触发的事件
        /// </summary>
        /// <param name="device"></param>
        private void DeviceManager_OnGetRecordingDevice(RecorderDevice device)
        {
            var status = new RecorderStatus();
            status.RecorderId = device.RecorderId;
            status.RecorderName = device.Name;
            status.State = (int)ResultCode.RecorderFree;
            status.Info = "";
            BurnRuntime.RecorderStatus.Add(status);

            Logger.Log("加载光驱设备：" + device.Name);
        }

        /// <summary>
        /// 检测一个光驱内光盘信息后触发的事件
        /// </summary>
        /// <param name="device"></param>
        /// <param name="info"></param>
        private void DeviceManager_OnDetectRecorder(RecorderDevice device, int resultCode, string info)
        {
            var status = BurnRuntime.GetRecorderStatus(device.RecorderId);
            if (status != null)
            {
                status.State = resultCode;
                status.Info = info;
            }

            Logger.Log("检测媒体信息：" + device.VolumePathName + " - code=" + resultCode + " " + info);
        }

        /// <summary>
        /// 检测光盘是否有足够容量刻录文件后触发的事件
        /// </summary>
        /// <param name="device"></param>
        /// <param name="totalDiscSize"></param>
        /// <param name="totalMediaSize"></param>
        private void DeviceManager_OnUpdateCapacity(RecorderDevice device, int resultCode, long totalDiscSize, long totalMediaSize)
        {
            string info = "媒体可用大小=" + PSDFunction.FormatByteSize(totalDiscSize) + "，待刻录内容大小=" + PSDFunction.FormatByteSize(totalMediaSize);

            var status = BurnRuntime.GetRecorderStatus(device.RecorderId);
            if (status != null)
            {
                status.State = resultCode;
                status.Info = info;
            }

            Logger.Log("检测媒体信息：" + device.VolumePathName + " - code=" + resultCode + " " + info);
        }

        /// <summary>
        /// 光盘刻录成功后触发的事件
        /// </summary>
        /// <param name="device"></param>
        /// <param name="dvd"></param>
        /// <param name="info"></param>
        private void DeviceManager_OnBurnSuccess(RecorderDevice device, BurnJob burnJob, string info)
        {
            burnJob.DVD.state = (int)BurnDVDState.刻录完成;
            burnJob.DVD.burn_end_time = DateTime.Now;

            BurnManager.EndBurnJob(device, burnJob);

            Logger.Log("刻录完成：" + device.VolumePathName + " " + burnJob.DVD.dvd_title + "-" + burnJob.DVD.dvd_num);
        }

        /// <summary>
        /// 光盘刻录失败后触发的事件
        /// </summary>
        /// <param name="device"></param>
        /// <param name="dvd"></param>
        /// <param name="info"></param>
        private void DeviceManager_OnBurnError(RecorderDevice device, BurnJob burnJob, string info)
        {
            burnJob.DVD.state = (int)BurnDVDState.刻录失败;
            burnJob.DVD.burn_end_time = DateTime.Now;
            burnJob.DVD.error_log = info;

            BurnManager.EndBurnJob(device, burnJob);

            Logger.Log("刻录失败：" + device.VolumePathName + " " + burnJob.DVD.dvd_title + "-" + burnJob.DVD.dvd_num + " " + info);
        }

        private void DeviceManager_OnBurnCancel(RecorderDevice device, BurnJob burnJob, string info)
        {
            burnJob.DVD.state = (int)BurnDVDState.刻录取消;
            burnJob.DVD.burn_end_time = DateTime.Now;
            burnJob.DVD.error_log = info;

            BurnManager.EndBurnJob(device, burnJob);

            Logger.Log("刻录失败：" + device.VolumePathName + " " + burnJob.DVD.dvd_title + "-" + burnJob.DVD.dvd_num + " " + info);
        }

        /// <summary>
        /// 更新光盘刻录进度时触发的事件
        /// </summary>
        /// <param name="device"></param>
        /// <param name="dvd"></param>
        /// <param name="info"></param>
        /// <param name="percent"></param>
        private void DeviceManager_OnBurnProgress(RecorderDevice device, BurnJob burnJob, string info, int percent)
        {
            burnJob.DVD.burn_percent = percent;

            Logger.Log("正在刻录：" + device.VolumePathName + " " + burnJob.DVD.dvd_title + "-" + burnJob.DVD.dvd_num + " " + info);
        }

        /// <summary>
        /// 执行接收到的刻录任务
        /// </summary>
        /// <param name="msg"></param>
        public void StartBurn(BurnTask task)
        {
            //BurnManager.AddTask(task);

            BurnManager.ImmediateBurn(task);
        }

        ///// <summary>
        ///// 添加一个待刻录文件
        ///// </summary>
        ///// <param name="burnId"></param>
        ///// <param name="file"></param>
        //public void AddBurnFile(string burnId, dl_files file)
        //{
        //    BurnManager.AddBurnFile(burnId, file);
        //}

        /// <summary>
        /// 返回刻录进度消息
        /// </summary>
        /// <param name="remoteEP"></param>
        public void ResponseBurnRuntime(IPEndPoint remoteEP)
        {
            var msg = new ResponseBurnRuntimeMessage();
            msg.BurnRuntime = BurnRuntime;

            ClientContext.MessageManager.Send(remoteEP, msg);
        }

        public void ResumeBurn()
        {
            BurnManager.Resume();
        }
    }

    public enum BurnType : int
    {
        单光驱刻录 = 1,
        双光驱刻录 = 2,
    }

    public enum BurnCopy : int
    {
        一式一份 = 1,
        一式两份 = 2,
    }
}
